#include <amxmodx>
#include <amxmisc>
#include <cstrike>
#include <fun>
#include <engine>

//#define USE_SQL

#if defined USE_SQL
#include <sqlx>
#else
#include <nvault>
#endif


#pragma semicolon 1
#define TASK_GIVE_AMMO 100
#define TASK_SET_CLIP 133
#define TASK_WAIT_FOR_PASS 166

#define NES_GLOBALS_INCLUDED 1

#define MAX_NAME_LEN 32

#define SAVE_TIME_ROUND_END "r"
#define SAVE_TIME_MAP_CHANGE "m"
#define SAVE_TIME_LAST_ROUND "l"
#define SAVE_TIME_PLAYER_COMMAND "s"

/*
	nes_active	(1)
		1/0 - 	enables/disables plugin
	nes_save_key	(0)
		0 -	Steam ID
		1 - 	Nick
	nes_save_frags	(1)
		1/0 -	enables/disables saving frags
	nes_save_weapons	(1)
		1/0 -	enables/disables saving weapons
	nes_save_money	(1)
		1/0 -	enables/disables saving money
	nes_save_HP 	(1)
		1/0 -	enables/disables saving HP
	nes_save_HP_in_map	(1)
		1/0 -	enables/disables saving HP on round end. In next round user will have this amount of hp
	nes_save_AP 	(1)
		1/0 -	enables/disables saving armour
	nes_save_flags	("dlr")
		r - 	Round end
		m - 	Map change
		l -	Last round end
		s -	Player command
*/

//{ CVARS
new gCvarActive;
new gCvarSaveKey;
new gCvarSaveFrags;
new gCvarSaveWeapons;
new gCvarSaveMoney;
new gCvarSaveFlags;
new gCvarSaveHP;
new gCvarSaveHPInMap;
new gCvarSaveAP;

new gCvarMP_ROUNDTIME;
new gCvarMP_TIMELIMIT;

//} // CVARS

#if defined USE_SQL
new gSqlTuple;
#else
new gVault;
new gVaultNicks;
#endif

enum PLAYER_INFO{
	PI_AUTHORIZED,
	PI_KEY[MAX_NAME_LEN],
	PI_CAN_PLAY,
	PI_HP
}
new gPlayerInfo[33][PLAYER_INFO];
new gMaxPlayers;

new const const_NES_PASS_FLD[] = "nes_pass";



public plugin_init_globals() {
	gMaxPlayers = get_maxplayers();
	gCvarActive = register_cvar("nes_active",  "1");
	gCvarSaveKey = register_cvar("nes_save_key",  "0");
	gCvarSaveFrags = register_cvar("nes_save_frags", "1");
	gCvarSaveWeapons = register_cvar("nes_save_weapons", "1");
	gCvarSaveMoney = register_cvar("nes_save_money", "1");
	gCvarSaveHP = register_cvar("nes_save_HP", "1");
	gCvarSaveHPInMap = register_cvar("nes_save_HP_in_map", "1");
	gCvarSaveAP = register_cvar("nes_save_AP", "1");

	gCvarSaveFlags = register_cvar("nes_save_flags", "dlr");
}

public client_connect_globals(id){
	clearPlayerInfo(id, 0);
}

stock isActive(){
	return get_pcvar_num(gCvarActive);
}
stock clearPlayerInfo(id, isNickChange ){
	if(!isNickChange){
		gPlayerInfo[id][PI_HP] =0;
	}
	gPlayerInfo[id][PI_KEY][0] = 0;
	gPlayerInfo[id][PI_AUTHORIZED] = 0;
	gPlayerInfo[id][PI_CAN_PLAY] = 0;
	
}
public client_disconnect_globals(id){
	
	clearPlayerInfo(id, 0);
	if(task_exists(TASK_GIVE_AMMO + id))
		remove_task(TASK_GIVE_AMMO + id);
	if(task_exists(TASK_SET_CLIP + id))
		remove_task(TASK_SET_CLIP + id);
}


stock is_player(id){
	return 0<id<gMaxPlayers;
}

stock canPlayerPlay(id) {
	if(!isActive())
		return 1;
	return gPlayerInfo[id][PI_CAN_PLAY];
}

public preparePlayer(id, money, frags, hp,ap,apTp, const weapons[32], const weaponsAmmo[32], const weaponsClip[32],  weaponsNum){
	if(!get_pcvar_num(gCvarActive))
		return;
	if(get_pcvar_num(gCvarSaveMoney))
		cs_set_user_money(id, money);		
	
	if(get_pcvar_num(gCvarSaveFrags))
		set_user_frags(id, frags);

	if(!is_user_alive(id))
		return;
		
	if(get_pcvar_num(gCvarSaveHP) && hp)
		set_user_health(id, hp);
	
	if(get_pcvar_num(gCvarSaveAP) && ap){
		cs_set_user_armor(id, ap, CsArmorType:apTp);
	}
	
	if(get_pcvar_num(gCvarSaveWeapons) && weaponsNum){
		new weapon;
		new clip;
		new ammo;
		new name[33];
		new hasBomb = user_has_weapon(id, CSW_C4);
		new wpn[3];
		strip_user_weapons(id);
		wpn[0] = id;
		
		for(new i=0;i<weaponsNum;i++){
			weapon = weapons[i];
			clip = weaponsClip[i];
			ammo = weaponsAmmo[i];
			
			get_weaponname(weapon, name, charsmax(name));
			give_item(id,name);			
			wpn[1] = weapon;
			wpn[2] = ammo;
			if(weapon != CSW_C4){
				if(ammo || clip ){
					set_task(0.1+i*0.1, "GiveAmmo", TASK_GIVE_AMMO + id, wpn);	
					wpn[2] = clip;
					set_task(0.11+i*0.1, "SetClip", TASK_SET_CLIP + id, wpn);	
				}
			}
		}
		if(hasBomb){
			give_item(id, "weapon_c4");
			cs_set_user_plant( id );
		}
	}
}

public GiveAmmo(wpn[]) {
	new player = wpn[0] - TASK_GIVE_AMMO;
	if(is_user_connected(player) && is_user_alive(player)) {
		new weapon = wpn[1];
		new ammo =  wpn[2];	
		cs_set_user_bpammo(player, weapon, ammo);
	}
}

public SetClip(wpn[]){
	new player = wpn[0] - TASK_SET_CLIP;
	if(is_user_connected(player) && is_user_alive(player)){
		new weapon = wpn[1];
		new clip =  wpn[2];
		new name[32];
		
		get_weaponname(weapon, name, charsmax(name));
		new weapon_id = find_ent_by_owner(-1, name, player);
		if(weapon_id) {
			cs_set_weapon_ammo(weapon_id, clip);
		} 
	}
}

stock shouldSave(const flag[]) {
	new flags[6];
	get_pcvar_string(gCvarSaveFlags, flags, 5);
	return contain(flags, flag);
}

stock bool:isLastRound(){
	new Float:roundTime = getRoundTimeSeconds();
	new Float:mapEndsIn = getSecondsToMapEnd();	
	if(roundTime > mapEndsIn)
		return true;
	return false;
}
stock Float:getSecondsToMapEnd(){
	return get_pcvar_float(gCvarMP_TIMELIMIT) * 60.0 - get_gametime();
}
stock Float:getRoundTimeSeconds(){
	return get_pcvar_float(gCvarMP_ROUNDTIME) * 60.0;
}
